JSON(JavaScript Object Notation,JS 对象简谱)是一种轻量级的数据交换格式。它是基于 ECMAScript(欧洲计算机协会制定的 JS 规范)的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。JSON 协议是一种文本协议,非常易于人阅读和编写,同时也易于机器解析和生成,并能有效地提升网络传输效率。
JSON 的序列化和反序列化实践
在实际开发中,目前主流的策略是Gson和FastJson结合使用。在 POJO序列化成JSON字符串的应用场景下,使用谷歌的Gson库;在 JSON 字符串反序列化成POJO的应用场景下,使用阿里巴巴的FastJson库。
1 2 3 4 5 6 7 8 9 10
| <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.10</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>2.0.60</version> </dependency>
|
工具类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| import com.alibaba.fastjson.JSONObject; import com.google.gson.GsonBuilder;
public class JsonUtil { static GsonBuilder gb = new GsonBuilder();
static { gb.disableHtmlEscaping(); }
public static String pojoToJson(java.lang.Object obj) { String json = gb.create().toJson(obj); return json; }
public static <T> T jsonToPojo(String json, Class<T> tClass) { T t = JSONObject.parseObject(json, tClass); return t; } }
|
业务代码测试:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| @Data public class JsonMsg { private int id; private String content;
public JsonMsg() {} public JsonMsg(int id, String content) { this.id = id; this.content = content; }
public String convertToJson() { return JsonUtil.pojoToJson(this); }
public static JsonMsg parseFromJson(String json) { return JsonUtil.jsonToPojo(json, JsonMsg.class); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| public class JsonMsgDemo { public JsonMsg buildMsg() { JsonMsg user = new JsonMsg(); user.setId(1000); user.setContent("密涅瓦的猫头鹰在黄昏起飞。"); return user; }
@Test public void serAndDesr() throws IOException { JsonMsg message = buildMsg(); String json = message.convertToJson(); System.out.println("json:=" + json);
JsonMsg inMsg = JsonMsg.parseFromJson(json); System.out.println("id:=" + inMsg.getId()); System.out.println("content:=" + inMsg.getContent()); } }
|
JSON传输的服务端的实战案例
为了清晰地演示JSON传输,下面设计一个简单的客户端/服务端传 输程序:客户端将POJO转换成JSON字符串,编码后发送到服务端。服务器接收客户端的数据包,并解码成JSON,再转换成 POJO。为了简化流程,此服务端的代码仅仅包含 Inbound 入站处理的流 程,不包含 OutBound 出站处理的流程,是一个“丢弃”服务器。也就是说,服务端的程序仅仅读取客户端数据包并完成解码,服务端的程 序没有写出任何输出数据包到对端(客户端)。服务端实战案例的程序代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
| import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.*; import io.netty.channel.nio.NioIoHandler; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.handler.codec.LengthFieldBasedFrameDecoder; import io.netty.handler.codec.string.StringDecoder; import io.netty.util.CharsetUtil; import utils.JsonMsg;
public class JsonServer { private final int port;
public JsonServer(int port) { this.port = port; }
public void runServer() { EventLoopGroup bossLoopGroup = new MultiThreadIoEventLoopGroup(1, NioIoHandler.newFactory()); EventLoopGroup workerLoopGroup = new MultiThreadIoEventLoopGroup(NioIoHandler.newFactory()); try { ServerBootstrap b = new ServerBootstrap(); b.group(bossLoopGroup, workerLoopGroup) .channel(NioServerSocketChannel.class) .option(ChannelOption.SO_BACKLOG, 128) .childOption(ChannelOption.SO_KEEPALIVE, true) .childHandler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) { ch.pipeline().addLast(new LengthFieldBasedFrameDecoder(1024, 0, 4, 0, 4));
ch.pipeline().addLast(new StringDecoder(CharsetUtil.UTF_8));
ch.pipeline().addLast(new JsonMsgDecoder()); } });
ChannelFuture f = b.bind(port).sync(); System.out.println("JSON 服务器启动成功,端口:" + port);
f.channel().closeFuture().sync(); } catch (InterruptedException e) { System.out.println("服务器运行异常:" + e.getMessage()); } finally { bossLoopGroup.shutdownGracefully(); workerLoopGroup.shutdownGracefully(); } }
static class JsonMsgDecoder extends ChannelInboundHandlerAdapter { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) { String json = (String) msg;
JsonMsg jsonMsg = JsonMsg.parseFromJson(json); System.out.println("收到一个 Json 数据包 =>> " + jsonMsg);
} }
public static void main(String[] args) { new JsonServer(9000).runServer(); } }
|
为了简化流程,客户端的代码仅仅包含Outbound出站处理的流 程,不包含Inbound入站处理的流程。也就是说,客户端的程序仅仅进 行数据的编码,然后把数据包写到服务端。客户端的程序并没有去处 理从对端(服务端)过来的输入数据包。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
| import io.netty.bootstrap.Bootstrap; import io.netty.channel.*; import io.netty.channel.nio.NioIoHandler; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.LengthFieldPrepender; import io.netty.handler.codec.string.StringEncoder; import io.netty.util.CharsetUtil; import utils.JsonMsg;
public class JsonSendClient { private final String serverIp; private final int serverPort;
public JsonSendClient(String ip, int port) { this.serverIp = ip; this.serverPort = port; }
public void runClient() { EventLoopGroup workerLoopGroup = new MultiThreadIoEventLoopGroup(NioIoHandler.newFactory()); try { Bootstrap b = new Bootstrap(); b.group(workerLoopGroup) .channel(NioSocketChannel.class) .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 5000) .handler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) { ch.pipeline().addLast(new LengthFieldPrepender(4));
ch.pipeline().addLast(new StringEncoder(CharsetUtil.UTF_8)); } });
ChannelFuture f = b.connect(serverIp, serverPort).sync(); System.out.println("已连接至服务端:" + serverIp + ":" + serverPort); Channel channel = f.channel();
String content = "密涅瓦的猫头鹰在黄昏起飞。"; for (int i = 0; i < 1000; i++) { JsonMsg message = new JsonMsg(i, i + " -> " + content); String json = message.convertToJson();
channel.writeAndFlush(json); System.out.println("发送第 " + i + " 个报文:" + json); }
channel.closeFuture().sync(); } catch (Exception e) { System.out.println("客户端运行异常: " + e.getMessage()); } finally { workerLoopGroup.shutdownGracefully(); } }
public static void main(String[] args) { new JsonSendClient("127.0.0.1", 9000).runClient(); } }
|
标题:
Java NIO - 序列化与反序列化 - 使用JSON协议通信